float BloomThresh;

float3 BloomTint;
float BloomSaturation;

float3 BaseTint;
float BaseSaturation;

#define SAMPLE_COUNT 15
float4 GaussianSamples[(SAMPLE_COUNT - 1) / 2];

float2 SourcePixelSize;
sampler SourceImage : register( s0 );
sampler BaseImage : register( s1 );

float4 post_proc_vs(
	float2 iPos : POSITION,
	float2 iTc : TEXCOORD0,
	
	out float2 oTc : TEXCOORD0
	) : POSITION
{
	oTc = iTc;
	return float4( iPos, 0, 1 );
}

float4 pass_through_ps( float2 iTc : TEXCOORD0 ) : COLOR
{
	return tex2D( SourceImage, iTc );
}

float luminance( float3 cl )
{
	return dot( cl, float3( 0.3, 0.59, 0.11 ) );
}

float4 bloom_extract_ps( float2 iTc : TEXCOORD0 ) : COLOR
{
	float3 cl;

#if 1

	cl = tex2D( SourceImage, iTc + float2( SourcePixelSize.x, SourcePixelSize.y ) ).rgb;
	cl += tex2D( SourceImage, iTc + float2( SourcePixelSize.x, -SourcePixelSize.y ) ).rgb;
	cl += tex2D( SourceImage, iTc + float2( -SourcePixelSize.x, -SourcePixelSize.y ) ).rgb;
	cl += tex2D( SourceImage, iTc + float2( -SourcePixelSize.x, SourcePixelSize.y ) ).rgb;
	
	cl *= 0.25;
	
#else

	cl = tex2D( SourceImage, iTc );
		
#endif
	
	float lum = luminance( cl );
	float adjLum = saturate( (lum - BloomThresh) / (1 - BloomThresh) );

	cl *= adjLum / lum;
	
	return float4( cl, 0 );
}

float4 bloom_blur_ps( float2 iTc : TEXCOORD0 ) : COLOR
{
	float3 cl = tex2D( SourceImage, iTc ).rgb * GaussianSamples[0].w; //center tap
	for( int i = 0; i < (SAMPLE_COUNT - 1) / 2; i++ )
	{
		cl += tex2D( SourceImage, iTc + GaussianSamples[i].xy ).rgb * GaussianSamples[i].z;
		cl += tex2D( SourceImage, iTc - GaussianSamples[i].xy ).rgb * GaussianSamples[i].z;
	}
	return float4( cl, 0 );
}

float3 adjust_saturation( float3 cl, float sat )
{
	float lum = luminance( cl );
	return lerp( lum, cl, sat );
}

float4 bloom_combine_ps( float2 iTc : TEXCOORD0 ) : COLOR
{
	float3 base = tex2D( BaseImage, iTc ).rgb;
	float3 bloom = tex2D( SourceImage, iTc ).rgb;

	bloom = adjust_saturation( bloom, BloomSaturation ) * BloomTint;
	base = adjust_saturation( base, BaseSaturation ) * BaseTint * (1 - saturate( bloom ));

	return float4( base + bloom, 0 );
}

technique Bloom
{
	pass Extract
	{
		VertexShader = compile vs_2_0 post_proc_vs();
		PixelShader = compile ps_2_0 bloom_extract_ps();
		
		ZEnable = False;
		AlphaTestEnable = False;
		AlphaBlendEnable = False;
	}
	
	pass Blur
	{
		VertexShader = compile vs_2_0 post_proc_vs();
		PixelShader = compile ps_2_0 bloom_blur_ps();
	}
	
	pass Combine
	{
		VertexShader = compile vs_2_0 post_proc_vs();
		PixelShader = compile ps_2_0 bloom_combine_ps();
	}
}

technique PassThrough
{
	pass p0
	{
		VertexShader = compile vs_2_0 post_proc_vs();
		PixelShader = compile ps_2_0 pass_through_ps();
		
		ZEnable = False;
		AlphaTestEnable = False;
		AlphaBlendEnable = False;
	}
}